using Testcontainers.PostgreSql;
using Testcontainers.MsSql;
using Testcontainers.MySql;
using Testcontainers.Redis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;
using Xunit;

namespace JGSY.CMS.LowCode.Platform.IntegrationTests.Fixtures;

/// <summary>
/// 数据库容器测试装置
/// </summary>
public class DatabaseContainerFixture : IAsyncLifetime
{
    // PostgreSQL 容器
    private readonly PostgreSqlContainer _postgresContainer = new PostgreSqlBuilder()
        .WithImage("postgres:15-alpine")
        .WithDatabase("testdb")
        .WithUsername("testuser")
        .WithPassword("testpass")
        .WithPortBinding(5432, true)
        .Build();

    // SQL Server 容器
    private readonly MsSqlContainer _sqlServerContainer = new MsSqlBuilder()
        .WithImage("mcr.microsoft.com/mssql/server:2022-latest")
        .WithPassword("YourStrong@Passw0rd")
        .WithPortBinding(1433, true)
        .Build();

    // MySQL 容器
    private readonly MySqlContainer _mysqlContainer = new MySqlBuilder()
        .WithImage("mysql:8.0")
        .WithDatabase("testdb")
        .WithUsername("testuser")
        .WithPassword("testpass")
        .WithPortBinding(3306, true)
        .Build();

    // Redis 容器
    private readonly RedisContainer _redisContainer = new RedisBuilder()
        .WithImage("redis:7-alpine")
        .WithPortBinding(6379, true)
        .Build();

    /// <summary>
    /// 获取 PostgreSQL 连接字符串
    /// </summary>
    public string PostgresConnectionString => _postgresContainer.GetConnectionString();

    /// <summary>
    /// 获取 SQL Server 连接字符串
    /// </summary>
    public string SqlServerConnectionString => _sqlServerContainer.GetConnectionString();

    /// <summary>
    /// 获取 MySQL 连接字符串
    /// </summary>
    public string MySqlConnectionString => _mysqlContainer.GetConnectionString();

    /// <summary>
    /// 获取 Redis 连接字符串
    /// </summary>
    public string RedisConnectionString => _redisContainer.GetConnectionString();

    /// <summary>
    /// 异步初始化容器
    /// </summary>
    public async Task InitializeAsync()
    {
        // 并行启动所有容器
        var tasks = new Task[]
        {
            _postgresContainer.StartAsync(),
            _sqlServerContainer.StartAsync(),
            _mysqlContainer.StartAsync(),
            _redisContainer.StartAsync()
        };

        await Task.WhenAll(tasks);
    }

    /// <summary>
    /// 异步清理容器
    /// </summary>
    public async Task DisposeAsync()
    {
        var disposeTasks = new Task[]
        {
            _postgresContainer.DisposeAsync().AsTask(),
            _sqlServerContainer.DisposeAsync().AsTask(),
            _mysqlContainer.DisposeAsync().AsTask(),
            _redisContainer.DisposeAsync().AsTask()
        };

        await Task.WhenAll(disposeTasks);
    }
}

/// <summary>
/// 使用容器的 Web 应用工厂
/// </summary>
public class ContainerWebApplicationFactory : WebApplicationFactory<Program>, IClassFixture<DatabaseContainerFixture>
{
    private readonly DatabaseContainerFixture _containerFixture;

    public ContainerWebApplicationFactory(DatabaseContainerFixture containerFixture)
    {
        _containerFixture = containerFixture;
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration((context, config) =>
        {
            // 添加测试配置，使用容器的连接字符串
            var testConfig = new Dictionary<string, string?>
            {
                ["ConnectionStrings:PostgreSQLConnection"] = _containerFixture.PostgresConnectionString,
                ["ConnectionStrings:DefaultConnection"] = _containerFixture.SqlServerConnectionString,
                ["ConnectionStrings:MySQLConnection"] = _containerFixture.MySqlConnectionString,
                ["Redis:ConnectionString"] = _containerFixture.RedisConnectionString,
                ["DatabaseType"] = "PostgreSQL", // 默认使用 PostgreSQL
                ["Logging:LogLevel:Default"] = "Information"
            };

            config.AddInMemoryCollection(testConfig);
        });

        builder.ConfigureServices(services =>
        {
            // 移除现有的数据库上下文配置
            var descriptors = services.Where(d => 
                d.ServiceType == typeof(DbContextOptions<LowCodeDbContext>) ||
                d.ServiceType == typeof(LowCodeDbContext)).ToList();
            
            foreach (var descriptor in descriptors)
            {
                services.Remove(descriptor);
            }

            // 使用 PostgreSQL 容器配置数据库
            services.AddDbContext<LowCodeDbContext>(options =>
            {
                options.UseNpgsql(_containerFixture.PostgresConnectionString);
                options.EnableSensitiveDataLogging();
            });

            // 确保数据库创建和迁移
            var sp = services.BuildServiceProvider();
            using var scope = sp.CreateScope();
            var db = scope.ServiceProvider.GetRequiredService<LowCodeDbContext>();
            
            try
            {
                db.Database.EnsureCreated();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"警告：数据库初始化失败：{ex.Message}");
            }
        });

        builder.UseEnvironment("Testing");
    }
}
